<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>ECMA测试</title>
  </head>
  <body>
    <script>
      //  1.  Javascript 的数据类型有几种？分别又有哪些类型？（5）
      /* 
      答：
        JavaScript的数据类型有：
            string、number、boolean、undefined、null、object、symbol、bigInt
            String、Number、Boolean、Undefined、Null、Object、Symbol、BigInt
       */

      //  2.  return 有那两个作用？ 构造函数里return会怎么样？（5）
      /* 
      答：
        return 的作用： 
          (1) 返回函数执行后的结果值
          (2) 终止函数执行
        构造函数里的return ：
          (1) 当return的是基本数据类型时，return返回值无效；
          (2) 当return的是一个对象时，则return返回值生效（包括return(返回)空对象）
       */

      //  3.  undefined 和 null 的区别？什么时候会得到undefined？（5）
      /* 
      答：
        (1) undefined 表示的是变量未定义；null 表示的是空；但是这两者在类型转化为布尔值时，会同样得到false值。
        (2) 当声明一个变量没有初始化(没有赋值)时，在控制台打印输出（使用该变量）,会得到undefined
       */

      //  4.  使用 continue 或 break 终止循环时，两种方式的区别是？（5）
      /* 
      答：
        continue 继续的意思，跳出当前循环体执行，继续执行下一次循环；
        break 打断的意思，打断当前循环体执行，终止执行之后的循环次数。
      */

      //  5.  如何判断字符串内是否包含指定字符？（5）
      /* 
      答：
        (1) 使用include()方法，返回值为布尔值boolean，若字符串包含指定字符，则返回true，否则返回false
        (2) 使用indexof()方法，若字符串包含指定字符，返回指定字符第一次出现的index下标，若不包含则返回-1
       */

      //  6. 值传递和引用传递的区别？ （5）
      /* 
      答：
        (1) 值传递，是基本数据类型之间的值传递，传递的是值本身。
        (2) 引用传递，是复杂数据类型（比如：对象、数组、函数）之间的引用传递，传递的是在内存中分配得到的地址值（引用、指针）。
       */

      //  7. 请尽量列举出数组的方法,并注明其作用以及会不会修改原数组，至少10种（10）
      /* 
      答：
        (1) length()  获取数组的长度，有可能会修改原数组
        (2) concat(arr1,[,...[,arrN]])  拼接数组，会修改原数组
        (3) slice(start,[,end])  截取数组，不会修改原数组  
        (4) splice()  用于增加或者删除或者修改 数组中间的元素，会修改原数组
        (5) push() 在数组尾部添加元素，会修改原数组
        (6) pop()  删除数组尾部的元素一次删除一个，会修改原数组
        (7) shift()  删除数组的头部元素，会修改原数组
        (8) unshift() 在数组头部添加元素，会修改原数组
        (9) join()  将数组转换成字符串，不会修改原数组
        (10) reduce(function (prov, index,item,arr) {},initial)  数组累加器 - 将数组进行迭代处理， 不会修改原数组
        (11) filter(function (index,item,arr) {}) 数组过滤器 - 将数组的值进行过滤到新的数组中，该数组存储的元素数据类型与原数组一样， 不会修改原数组
        (12) map(function (index,item,arr) {}) 数组映射 - 将数组映射到另外一个数组中，该数组存储的元素数据类型与原数组可能不一样，不会修改原数组
        (13) sort() 数组元素顺序从小到大排序(a-b)或者从大到小排序(b-a)
        (14) reverse() 将数组元素顺序翻转
        */

      //  8.  请写出以下输出的结果和原因；（10）
      var bar = true,
        number = 0;
      console.log(bar + 0);             // 结果为1，Boolean类型的true在数字做'+'操作时会隐式转换为Number类型的数字1，与数字做算术运算的加运算
      console.log(bar + 'xyz');         // 结果为truexyz，与字符串做'+'操作会拼接字符串
      console.log(bar + true);          // 结果为2，Boolean类型的true在做算术运算时会隐式转换为Number类型的数字1，再做算数运算
      console.log(+true);               // 结果为1，隐式转换为数字1
      console.log(!'bluej');            // 结果为false,"!"为逻辑运算的非运算，字符串隐式转换为true，然后取反
      console.log(number++);            // 结果为0，变量number先打印输出，然后才自增1的 （后置++，先用后增）
      console.log(++number);            // 结果为2，变量number在上语句中已经自增为1，在这里则先自增然后打印输出。（前置++，先增后用）
      console.log(number);              // 结果为2，自增了两次
      10 > 20 || console.log('haha');   // 结果为"haha"，这里是短路“或”逻辑运算，若遇到true值，则"||"后边的语句就不会。
      10 > 20 && console.log('haha');   // 没有输出，这是短路“与”逻辑运算，若遇到false值，则"&&"后边的语句就不会执行

      //  9. 将多个数组进合并后再去重；对于去重的方案要求3种及以上（10）
      var arr1 = [1, 2, 3],
        arr2 = [2, 3, 4, 5];
      var newArr = arr1.concat(arr2);
      // 使用Set集合中元素唯一的特性
      [...new Set(newArr)];  
      // 使用splice方法，要注意数组塌陷
      for(var i = 0; i < newArr.length; i++) {
        if(newArr[i] === newArr[i+1]){
          newArr.splice(i, 1);
          newArr.includes
          i--;
        }
      }
      // 使用includes方法，或者indexof方法
      var emptyArr1 = [];
      for(var item of newArr){
        if(!emptyArr1.includes(item)){
          emptyArr1.push(item);
        }
      }

      //10.将 str="再见，还会再见吗燕子，再见的时候你要幸福好不好，燕子你要开心，你要幸福，好不好，开心啊，幸福！你的世界以后没有我了，没关系你要幸福，🚗~~ 🏃🏻~~燕子 🧎🏻燕子~~没有你我怎么活啊🚗~~ 🏃🏻~~燕子 🧎🏻燕子~~没有你我怎么活啊🚗~~ 🏃🏻~~燕子 🧎🏻燕子~~没有你我怎么活啊燕子，燕子，燕子，燕子，燕子，燕子，燕子你把我带走吧，燕子！"里面的所有"燕子"替换成"jack"不要用replaceAll(10)
      var str = "再见，还会再见吗燕子，再见的时候你要幸福好不好，燕子你要开心，你要幸福，好不好，开心啊，幸福！你的世界以后没有我了，没关系你要幸福，🚗~~ 🏃🏻~~燕子 🧎🏻燕子~~没有你我怎么活啊🚗~~ 🏃🏻~~燕子 🧎🏻燕子~~没有你我怎么活啊🚗~~ 🏃🏻~~燕子 🧎🏻燕子~~没有你我怎么活啊燕子，燕子，燕子，燕子，燕子，燕子，燕子你把我带走吧，燕子！";
      var newName = "jack";
      for(var i = 0; i < str.length; i++) {
        if(str.includes("燕子")){
          str = str.replace("燕子","jack");
        }
      }

      //11. 找出数组中年龄小于18岁的女生(girl)的信息重新组成新的数组,并且将她们count变为现有的平方（10）
      var arr3 = [
        { name: '彭于晏', sex: 'boy', age: 18, count: 20 },
        { name: '迪丽热巴', sex: 'girl', age: 17, count: 30 },
        { name: '吴彦祖', sex: 'boy', age: 16, count: 40 },
        { name: '古力娜扎', sex: 'girl', age: 15, count: 50 },
        { name: '刘德华', sex: 'boy', age: 20, count: 60 },
        { name: '刘亦菲', sex: 'girl', age: 13, count: 70 },
        { name: '张学友', sex: 'boy', age: 14, count: 80 },
      ];
      arr3.filter(function (item) {
        return item.age < 18;
      })
      .map(function (item) {
        return item.count**2;
      });

      // 12. 统计字符串'abbcccddddd'中每个字符出现的次数，统计数组['a','b','b','c','c','c','d','d','d','d','d'中每个字符出现的次数(10分)
      var str12 = "abbcccddddd";
      var arr12 = ['a','b','b','c','c','c','d','d','d','d','d'];
      var newStr = arr12.join('');
      function countChar(str){
        var obj = {};
        for(var i = 0; i < str.length; i++) {
          obj[str[i]] ? (obj[str[i]] += 1) : (obj[str[i]] = 1);
        }
        for(var k in obj){
            console.log( k + "出现的次数为"+obj[k]);
        }
      }
      countChar(str12);
      countChar(newStr);
      
    </script>
  </body>
</html>
